#!/usr/bin/env bash
set -e

# usage: clean-branches
# Deletes any local branches which are ancestors of origin/master,
# and also any branches in origin which are ancestors of
# origin/master and are named like $USER-*.

# usage: clean-branches --reviews
# Deletes all the above mentioned branches as well as branches
# created by the scripts like `fetch-rebase-pull-request`. Be careful
# as this would also remove other branches woth names like review-*

review=0
if [ $# -ne 0 ] && [ "$1" == "--reviews" ]; then
    review=1
fi
push_args=()

function is_merged {
    ! git rev-list -n 1 origin/master.."$1" | grep -q .
}

function clean_ref {
    ref="$1"
    case "$ref" in
        */master | */HEAD)
            return
            ;;

        refs/heads/review-*)
            if [ $review -ne 0 ]; then
                echo -n "Deleting local branch ${ref#refs/heads/}"
                echo " (was $(git rev-parse --short "$ref"))"
                git update-ref -d "$ref"
            fi
            ;;

        refs/heads/*)
            if is_merged "$ref"; then
                echo -n "Deleting local branch ${ref#refs/heads/}"
                echo " (was $(git rev-parse --short "$ref"))"
                git update-ref -d "$ref"
            fi
            ;;

        refs/remotes/origin/$USER-*)
            if is_merged "$ref"; then
                remote_name="${ref#refs/remotes/origin/}"
                echo -n "Deleting remote branch $remote_name"
                echo " (was $(git rev-parse --short "$ref"))"
                # NB: this won't handle spaces in ref names
                push_args=("${push_args[@]}" ":$remote_name")
            fi
            ;;
    esac
}

if [ "$(git symbolic-ref HEAD)" != 'refs/heads/master' ]; then
    echo "Check out master before you run this script." >&2
    exit 1
fi

git fetch --prune origin

eval "$(git for-each-ref --shell --format='clean_ref %(refname);')"

if [ "${#push_args}" -ne 0 ]; then
    git push origin "${push_args[@]}"
fi
